package com.jasonchoi.redisqueue.queue;

import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 消息队列重试
 * @Author: JasonChoi
 * @Date: 2020/3/23 15:12
 */
@Log4j2
@Component
public class RedisQueueRetryHandler {
    /**
     * 重试频率
     */
    private List<Long> retryFrequency = Arrays.asList(1L, 3L, 5L);
    /**
     * 重试时间单位
     */
    private TimeUnit retryTimeUnit = TimeUnit.MINUTES;

    @Autowired
    private RedisQueueUtil redisQueueUtil;

    public void retryHandle(String topicKey, Object message) {
        if(retryFrequency.isEmpty()){
            return;
        }
        QueueRetryMsg retryKey = new QueueRetryMsg(topicKey, message);
        int retrySize = retryFrequency.size();
        String tip = "队列重试机制触发，重试次数：{}/{}， 重试时间{}分钟后，TOPIC:{},MESSAGE:{}";
        String failedMsg = JSONObject.toJSONString(retryKey);
        Integer retryCount = redisQueueUtil.getRetryCount(failedMsg);
        if (Objects.isNull(retryCount)) {
            Long time = retryFrequency.get(0);
            redisQueueUtil.publish(message, time, TimeUnit.MINUTES, topicKey);
            redisQueueUtil.recordFailed(failedMsg, 1);
            log.info(tip, 1, retrySize, time, topicKey, message);
            return;
        }
        if (retryCount < retrySize) {
            Long time = retryFrequency.get(retryCount);
            redisQueueUtil.recordFailed(failedMsg, ++retryCount);
            redisQueueUtil.publish(message, time, retryTimeUnit, topicKey);
            log.info(tip, retryCount, retrySize, time, topicKey, message);
        } else {
            log.info("队列重试机制已耗尽!!! TOPIC:{}, MESSAGE:{}", retryTimeUnit, message);
            redisQueueUtil.removeFailed(failedMsg);
        }
    }

    @Data
    @Accessors(chain = true)
    @AllArgsConstructor
    public static class QueueRetryMsg{
        String topicKey;
        Object message;
    }
}
